package uk.ac.open.kmi.dyniqx.wrappers;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Hashtable;

import javax.servlet.http.*;

import org.apache.log4j.Logger;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import org.directwebremoting.proxy.dwr.Util;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import uk.ac.open.kmi.dyniqx.repositories.GoogleScholarThread;
import uk.ac.open.kmi.dyniqx.repositories.IntuteThread;
import uk.ac.open.kmi.dyniqx.repositories.PerXThread;
import uk.ac.open.kmi.dyniqx.repositories.PubMedThread;
import uk.ac.open.kmi.dyniqx.repositories.GoogleImagesThread;
import uk.ac.open.kmi.dyniqx.repositories.YahooImagesThread;
import uk.ac.open.kmi.dyniqx.repositories.GoogleVideoThread;
import uk.ac.open.kmi.dyniqx.storages.Storage;

public class SessionWrapper {

	private Storage storage;
	private RepositoryWrapper repositoryWrapper;
	
	public Logger logger = Logger.getLogger("uk.ac.open.kmi.dyniqx.wrappers.SessionWrapper");
	
	public SessionWrapper() {
		this.logger.debug("SessionWrapper instance created.");
	}
	
	public void manageQuery(HttpServletRequest request) {
		this.logger.debug("Manage SW for " + request.getSession().getId() + ".");
	}
	
    public void addQuery(String text) {

    	this.logger.debug("Trying to add: " + text);
    	
    	this.logger.debug(this.repositoryWrapper);
    	
    	this.storage.setWctx(WebContextFactory.get());
		this.repositoryWrapper.searchRepositories(text.trim());
    }
    
    public void resetPool() {
    	
    	this.logger.debug("Trying to reset pool");
   	
    	if (this.storage.getQueryWrapper().size() == 0 && this.storage.getInsertedIDs().size() == 0) {
    		this.logger.debug("Empty pool, nothing to clear.");
    		
    		return;
    	}
    	
    	ThreadGroup root = Thread.currentThread().getThreadGroup();
               
        int numThreads = root.activeCount();
        Thread[] threads = new Thread[numThreads*2];
        numThreads = root.enumerate(threads, false);

        for (int i=0; i<numThreads; i++) {

        	Thread thread = threads[i];
            System.out.println(thread.getName());           
            
            WebContext wctx = WebContextFactory.get();
            
            if (thread.getName().startsWith("PMT-" + wctx.getSession().getId()) && thread != Thread.currentThread()) {
            	PubMedThread pmt = (PubMedThread) thread;  
            	pmt.stop = true;
            }

            if (thread.getName().startsWith("INT-" + wctx.getSession().getId()) && thread != Thread.currentThread()) {
            	IntuteThread pmt = (IntuteThread) thread;  
            	pmt.stop = true;
            }
            
            if (thread.getName().startsWith("GS-" + wctx.getSession().getId()) && thread != Thread.currentThread()) {
            	GoogleScholarThread pmt = (GoogleScholarThread) thread;  
            	pmt.stop = true;
            }
            
            if (thread.getName().startsWith("PRX-" + wctx.getSession().getId()) && thread != Thread.currentThread()) {
            	PerXThread pmt = (PerXThread) thread;  
            	pmt.stop = true;
            }
            
            if (thread.getName().startsWith("GIm-" + wctx.getSession().getId()) && thread != Thread.currentThread()) {
            	GoogleImagesThread pmt = (GoogleImagesThread) thread;  
            	pmt.stop = true;
            }
            
            if (thread.getName().startsWith("YIm-" + wctx.getSession().getId()) && thread != Thread.currentThread()) {
            	YahooImagesThread pmt = (YahooImagesThread) thread;  
            	pmt.stop = true;
            }
            
            if (thread.getName().startsWith("GVi-" + wctx.getSession().getId()) && thread != Thread.currentThread()) {
            	GoogleVideoThread pmt = (GoogleVideoThread) thread;  
            	pmt.stop = true;
            }
        }

        this.storage.performIOAction(Storage.CLEAR_ACTION, true);
        this.storage.getQueryWrapper().clear();
        this.storage.getInsertedIDs().clear();
        this.storage.updateGrid();
    }

	@SuppressWarnings("unchecked")
    public void fetchNewTerms() {

    	this.logger.debug("Getting new terms");
    	
		String results = (String) this.storage.performIOAction(Storage.FETCH_ACTION, null);

    	Util utilThis = new Util(this.storage.getWctx().getScriptSession());
    	utilThis.setValue("terms-dumping", results);
    	utilThis.addFunctionCall("Dyniqx.parseIndexedTerms");
    }
	
	@SuppressWarnings("unchecked")
    public Object retrieveResults(String query) {
    	
    	this.logger.debug("Retrieving results");

		ArrayList<Hashtable<String, Object>> results = (ArrayList<Hashtable<String, Object>>) this.storage.performIOAction(Storage.READ_ACTION, query);
    	
    	return results; 
    }
    
	@SuppressWarnings("unchecked")
    public Object invokeExpertSearch(String queryString) throws UnsupportedEncodingException, JDOMException, IOException {
    	
    	this.logger.debug("Searching for experts...");

		String baseUrl = "http://expertsearch.open.ac.uk/pubMedWebService/Service1.asmx/pubMedExpertSearch?retrieveSupportDocs=false&userQuery=";

		SAXBuilder parser = new SAXBuilder();
		Document doc = parser.build(baseUrl + URLEncoder.encode(queryString, "UTF-8"));		
		String content = doc.getRootElement().getText();		
    	
	    content = content.replaceAll("<expert><name>", "{name:'");
	    content = content.replaceAll("</name><score>", "',score:'");
	    content = content.replaceAll("</score></expert>", "'},");

	    if (content.length() > 0) content = content.substring(0, content.length()-1);
	    
	    content = "[" + content + "]";
	    
    	return content; 
    }
	
	public Storage getStorage() {
		return storage;
	}

	public void setStorage(Storage storage) {
		this.storage = storage;
	}

	public RepositoryWrapper getRepositoryWrapper() {
		return repositoryWrapper;
	}

	public void setRepositoryWrapper(RepositoryWrapper repositoryWrapper) {
		this.repositoryWrapper = repositoryWrapper;
	}
}